package com.ai.wxy.spring.jpa.user.service;

import com.ai.spring.common.enums.DataStatusEnum;
import com.ai.spring.common.enums.ExceptionEnum;
import com.ai.spring.common.exception.ServiceException;
import com.ai.wxy.spring.jpa.user.convert.UserDTOConvert;
import com.ai.wxy.spring.jpa.user.dao.MenuRolePermDao;
import com.ai.wxy.spring.jpa.user.dao.RolePermDao;
import com.ai.wxy.spring.jpa.user.dao.UserDao;
import com.ai.wxy.spring.jpa.user.dao.UserRoleDao;
import com.ai.wxy.spring.jpa.user.dto.MenuRolePermDTO;
import com.ai.wxy.spring.jpa.user.dto.UserDTO;
import com.ai.wxy.spring.jpa.user.entity.MenuRolePerm;
import com.ai.wxy.spring.jpa.user.entity.RolePerm;
import com.ai.wxy.spring.jpa.user.entity.User;
import com.ai.wxy.spring.jpa.user.entity.UserRole;
import com.ai.wxy.spring.jpa.user.query.UserRolePermQuery;
import com.ai.wxy.spring.service.api.BaseService;
import com.ai.wxy.spring.service.api.dto.DefaultServiceParam;
import com.ai.wxy.spring.service.api.dto.DefaultServiceResult;
import com.ai.wxy.spring.service.api.dto.ServiceResultList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户角色权限服务
 *
 * @author 石头
 * @Date 2019/11/19
 * @Version 1.0
 **/
@Service
public class UserRolePermService implements IUserRolePermService{
    @Autowired
    private UserDao userDao;
    @Autowired
    private UserRoleDao userRoleDao;
    @Autowired
    private MenuRolePermDao menuRolePermDao;
    @Autowired
    private RolePermDao rolePermDao;
    @Autowired
    private UserDTOConvert convert;

    /**
     * 获取所有菜单权限列表
     * @return
     */
    public ServiceResultList<MenuRolePermDTO> getAllMenuPerms(DefaultServiceParam<Long> param){
        MenuRolePerm menuRolePerm = new MenuRolePerm();
        menuRolePerm.setStatus(DataStatusEnum.VALID.getCode());
        List<MenuRolePerm> menuPerms = menuRolePermDao.findBySenstive(menuRolePerm);
        if (CollectionUtils.isEmpty(menuPerms)){
            throw new ServiceException(ExceptionEnum.DATA_NO_EXIST,"菜单权限数据");
        }

        // 获取角色权限列表
        List<Long> roleIds = menuPerms.stream().map(MenuRolePerm::getRoleId).distinct().collect(Collectors.toList());
        List<RolePerm> rolePerms = findRolesPerm(roleIds);
        if (CollectionUtils.isEmpty(rolePerms)){
            throw new ServiceException(ExceptionEnum.DATA_NO_EXIST,"角色权限数据");
        }
        Map<Long,List<RolePerm>> rolePermMap = rolePerms.stream().collect(Collectors.groupingBy(RolePerm::getRoleId));

        // 转换结果数据
        List<MenuRolePermDTO> result = new ArrayList<>();
        menuPerms.stream().forEach(menu -> {
            List<RolePerm> rolePermList = rolePermMap.get(menu.getRoleId());
            if (!CollectionUtils.isEmpty(rolePermList)){
                List<String> rolerPermCodes = rolePermList.stream().map(RolePerm::getPermCode).distinct().collect(Collectors.toList());

                List<MenuRolePermDTO> menuCodes = rolerPermCodes.stream().map(code -> {
                    MenuRolePermDTO menuRolePermDTO = new MenuRolePermDTO();
                    menuRolePermDTO.setId(menu.getId());
                    menuRolePermDTO.setMenuUrlPattern(menu.getMenuUrlPattern());
                    menuRolePermDTO.setPermCode(code);
                    return menuRolePermDTO;
                }).collect(Collectors.toList());

                result.addAll(menuCodes);
            }
        });

        return new ServiceResultList(result);
    }

    /**
     * 按用户名查询用户信息
     * @param userName
     * @return
     */
    public DefaultServiceResult<UserDTO> findUserByName(DefaultServiceParam<String> userName){
        if (userName==null || StringUtils.isEmpty(userName.getParam())){
            throw new ServiceException(ExceptionEnum.PARAM_NO_EXIST,"用户名称");
        }
        User user = new User();
        user.setUsername(userName.getParam());
        user.setStatus(DataStatusEnum.VALID.getCode());
        List<User> datas = userDao.findBySenstive(user);
        if (CollectionUtils.isEmpty(datas)){
            throw new ServiceException(ExceptionEnum.DATA_NO_EXIST,"用户:"+userName);
        }
        return DefaultServiceResult.build(convert.toDto(datas.get(0)));
    }

    /**
     * 获取用户的权限列表
     * @param userId
     * @return
     */
    public ServiceResultList<DefaultServiceParam<String>> findUserRoles(DefaultServiceParam<Long> userId){
        if (userId == null || userId.getParam() == null){
            throw new ServiceException(ExceptionEnum.PARAM_NO_EXIST,"用户ID");
        }
        UserRole userRole = new UserRole();
        userRole.setUserId(userId.getParam());
        userRole.setStatus(DataStatusEnum.VALID.getCode());
        List<UserRole> userRoles = userRoleDao.findBySenstive(userRole);
        if (CollectionUtils.isEmpty(userRoles)){
            throw new ServiceException(ExceptionEnum.DATA_NO_EXIST,"用户角色:"+userId.getParam());
        }

        // 根据角色Id查询角色对应的权限列表
        List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        List<RolePerm> userPerms = findRolesPerm(roleIds);
        if (CollectionUtils.isEmpty(userPerms)){
            throw new ServiceException(ExceptionEnum.DATA_NO_EXIST,"用户权限:"+userId.getParam());
        }

        List<String> permCodes = userPerms.stream().map(RolePerm::getPermCode).distinct().collect(Collectors.toList());
        List<DefaultServiceParam<String>> results = permCodes.stream().map(code -> DefaultServiceParam.build(code)).collect(Collectors.toList());
        return new ServiceResultList(results);
    }

    /**
     * 根据角色Id查询角色对应的权限列表
     * @param roleIds
     * @return
     */
    private List<RolePerm> findRolesPerm(List<Long> roleIds){
        UserRolePermQuery rolePermQuery = new UserRolePermQuery();
        rolePermQuery.setRoleIds(roleIds);
        RolePerm rolePerm = new RolePerm();
        rolePerm.setStatus(DataStatusEnum.VALID.getCode());
        List<RolePerm> userPerms = rolePermDao.queryByCriteria(rolePermQuery,rolePerm);
        return userPerms;
    }
}
